﻿Option Strict On

Imports System.Data
Imports System.Data.Common
Imports System.Collections.Specialized
Imports log4net

Public Class DbDataRepository
	
	#Region "Für Singleton Pattern"
	
	Protected Shared _instance As DbDataRepository
	
	Public Shared Function GetInstance() As DbDataRepository
		If _instance Is Nothing Then _
			_instance = New DbDataRepository()
		Return _instance
	End Function
	
	#End Region
	
	''' <summary>
	''' Liefert die Funktionen für das Loggen mit log4net
	''' </summary>
	Private _ilog As ILog


    Private _isDebugEnabled As Boolean
    Private _isErrorEnabled As Boolean

	Protected Sub New()
        _ilog = LogManager.GetLogger(GetType(DbDataRepository))
        _isDebugEnabled = _ilog.IsDebugEnabled
        _isErrorEnabled = _ilog.IsErrorEnabled
	End Sub
	
	
	''' <summary>
    ''' Speichert die erzeugten und abzurufenden de+r DbDataService Instanzen
	''' </summary>
	''' <remarks></remarks>
    Private _factoryStorage As New HybridDictionary
	

	''' <summary>
	''' Liefert einen ConnectionStringBuilder für einen ProviderName
	''' </summary>
	''' <param name="providerName">ProviderName zur ADO.NET Library</param>
	Public Overridable Function GetDbConnectionStringBuilder(ByVal providerName As String) As DbConnectionStringBuilder
		Return DbProviderFactories.GetFactory(providerName).CreateConnectionStringBuilder()
	End Function


    ''' <summary>
    ''' Liefert die Liste aller Keys zu den registrierten DbDataServices
    ''' </summary>
    Public ReadOnly Property Keys As System.Collections.ICollection
        Get
            Return _factoryStorage.Keys
        End Get
    End Property


    ''' <summary>
    ''' Löscht einen DbDataService anhand des ConnectionNames
    ''' </summary>
    ''' <param name="key"></param>
    ''' <remarks></remarks>
    Public Sub Remove(ByVal key As String)
        _factoryStorage.Remove(key)
        If _isDebugEnabled Then _
            _ilog.DebugFormat("DbDataService mit dem Key '{0}' entfernt.", key)
    End Sub

	
	''' <summary>
	''' Liefert und initialisiert ggf. einen DbDataService für einen Provider mit einer bestimmten Verbindung.
	''' </summary>
	''' <param name="connectionName">Name der Verbindung, unter dem sie auch gespeichert wird und abzurufen ist.</param>
	''' <param name="connectionString">Der Connectionstring zur Datenbank</param>
	''' <param name="providerName">Der zu verwendende Provider zur ADO.NET Library</param>
	Public Overridable Overloads Function GetDbDataService(ByVal connectionName As String, ByVal connectionString As String, ByVal providerName As String) As DbDataService
		
		If Not _factoryStorage.Contains(connectionName) Then
			_factoryStorage.Add(connectionName, New DbDataService(connectionName, _
				providerName, _
				connectionString))

            If _isDebugEnabled Then _
                _ilog.DebugFormat("DbDataService für {0} mit Provider {1} erstellt.", New Object() {connectionName, providerName})
		End If
		
		Return CType(_factoryStorage(connectionName), DbDataService)
		
	End Function
	
	
	''' <summary>
	''' Liefert einen DbDataService anhand des Verbindungsnamens, der beim initialisieren mitgegeben wurde.
	''' </summary>
	''' <param name="connectionName">Name der Verbindung</param>
	''' <remarks>Wenn nichts gefunden wird, wird eine NullReferenceException geworfen.</remarks>
	Public Overridable Overloads Function GetDbDataService(ByVal connectionName As String, Optional ByVal tryCheckConfig As Boolean = False) As DbDataService
		
		' wenn der dbdataservice nicht existiert
		If Not _factoryStorage.Contains(connectionName) Then
			
			' wenn in der app.config nachgesehen werden soll
			If tryCheckConfig Then
				
				Try
					' die andere methode versuchen lassen das dbdataservice objekt erzeugen zu lassen
					' wenn das nicht funktioniert bzw. kein eintrag in der app.conig existiert, wird eine excpetion geworfen.
					Return Me.GetDbDataService(connectionName, _
						System.Configuration.ConfigurationManager. _
						ConnectionStrings(connectionName).ConnectionString, _
						System.Configuration.ConfigurationManager. _
						ConnectionStrings(connectionName).ProviderName)
				Catch nrex As NullReferenceException

                    If _isErrorEnabled Then _
                        _ilog.Error(String.Format( _
                                    "Fehler beim Erstellen eines DbDataService mit Informationen aus der App.config. ConnectionName: {0}", _
                                    New Object() {connectionName}), nrex)
					
					' die entstandene fehlermeldung  abfragen und mit eigenen informationen füllen.
					' dann ebenfalls eine nullreferenceexception werfen.
					Throw New NullReferenceException(String.Format("Es existiert kein DbDataService für den Connection-Namen '{0}' in der Anwendungskonfigurationdatei.", _
					connectionName), nrex)
				End Try
				
			Else
				
                If _isErrorEnabled Then _
                    _ilog.Error(String.Format("Fehler beim Liefern eines DbDataService. ConnectionName: {0}", _
                                New Object() {connectionName}), Nothing)
				
				Throw New NullReferenceException(String.Format("Es existiert kein DbDataService für den Connection-Namen '{0}'", connectionName))
				
			End If
			
		Else
			
			Return CType(_factoryStorage(connectionName), DbDataService)
			
		End If
		
	End Function
	
End Class